'use strict';

/**
 * app.directives
 */
angular.module('app.directives', ['ui.load'])
  .directive('uiModule', ['MODULE_CONFIG','uiLoad', '$compile', function(MODULE_CONFIG, uiLoad, $compile) {
    return {
      restrict: 'A',
      compile: function (el, attrs) {
        var contents = el.contents().clone();
        return function(scope, el, attrs){
          el.contents().remove();
          uiLoad.load(MODULE_CONFIG[attrs.uiModule])
          .then(function(){
            $compile(contents)(scope, function(clonedElement, scope) {
              el.append(clonedElement);
            });
          });
        }
      }
    };
  }])
  .directive('uiShift', ['$timeout', function($timeout) {
    return {
      restrict: 'A',
      link: function(scope, el, attr) {
        // get the $prev or $parent of this el
        var _el = $(el),
            _window = $(window),
            prev = _el.prev(),
            parent,
            width = _window.width()
            ;

        !prev.length && (parent = _el.parent());
        
        function sm(){
          $timeout(function () {
            var method = attr.uiShift;
            var target = attr.target;
            _el.hasClass('in') || _el[method](target).addClass('in');
          });
        }
        
        function md(){
          parent && parent['prepend'](el);
          !parent && _el['insertAfter'](prev);
          _el.removeClass('in');
        }

        (width < 768 && sm()) || md();

        _window.resize(function() {
          if(width !== _window.width()){
            $timeout(function(){
              (_window.width() < 768 && sm()) || md();
              width = _window.width();
            });
          }
        });
      }
    };
  }])
  .directive('uiToggleClass', ['$timeout', '$document', function($timeout, $document) {
    return {
      restrict: 'AC',
      link: function(scope, el, attr) {
        el.on('click', function(e) {
          e.preventDefault();
          var classes = attr.uiToggleClass.split(','),
              targets = (attr.target && attr.target.split(',')) || Array(el),
              key = 0;
          angular.forEach(classes, function( _class ) {
            var target = targets[(targets.length && key)];            
            ( _class.indexOf( '*' ) !== -1 ) && magic(_class, target);
            $( target ).toggleClass(_class);
            key ++;
          });
          $(el).toggleClass('active');

          function magic(_class, target){
            var patt = new RegExp( '\\s' + 
                _class.
                  replace( /\*/g, '[A-Za-z0-9-_]+' ).
                  split( ' ' ).
                  join( '\\s|\\s' ) + 
                '\\s', 'g' );
            var cn = ' ' + $(target)[0].className + ' ';
            while ( patt.test( cn ) ) {
              cn = cn.replace( patt, ' ' );
            }
            $(target)[0].className = $.trim( cn );
          }
        });
      }
    };
  }])
  .directive('uiNav', ['$timeout', function($timeout) {
    return {
      restrict: 'AC',
      link: function(scope, el, attr) {
        var _window = $(window), 
        _mb = 768, 
        wrap = $('.app-aside'), 
        next, 
        backdrop = '.dropdown-backdrop';
        // unfolded
        el.on('click', 'a', function(e) {
          next && next.trigger('mouseleave.nav');
          var _this = $(this);
          _this.parent().siblings( ".active" ).toggleClass('active');
          _this.next().is('ul') &&  _this.parent().toggleClass('active') &&  e.preventDefault();
          // mobile
          _this.next().is('ul') || ( ( _window.width() < _mb ) && $('.app-aside').removeClass('show off-screen') );
        });

        // folded & fixed        
        el.on('mouseenter', 'a', function(e){
          next && next.trigger('mouseleave.nav');
          $('> .nav', wrap).remove();
          if ( !$('.app-aside-fixed.app-aside-folded').length || ( _window.width() < _mb )) return;
          var _this = $(e.target)
          , top
          , w_h = $(window).height()
          , offset = 50
          , min = 150;

          !_this.is('a') && (_this = _this.closest('a'));
          if( _this.next().is('ul') ){
             next = _this.next();
          }else{
            return;
          }
         
          _this.parent().addClass('active');
          top = _this.parent().position().top + offset;
          next.css('top', top);
          if( top + next.height() > w_h ){
            next.css('bottom', 0);
          }
          if(top + min > w_h){
            next.css('bottom', w_h - top - offset).css('top', 'auto');
          }
          next.appendTo(wrap);

          next.on('mouseleave.nav', function(e){
            $(backdrop).remove();
            next.appendTo(_this.parent());
            next.off('mouseleave.nav').css('top', 'auto').css('bottom', 'auto');
            _this.parent().removeClass('active');
          });

          $('.smart').length && $('<div class="dropdown-backdrop"/>').insertAfter('.app-aside').on('click', function(next){
            next && next.trigger('mouseleave.nav');
          });

        });

        wrap.on('mouseleave', function(e){
          next && next.trigger('mouseleave.nav');
          $('> .nav', wrap).remove();
        });
      }
    };
  }])
  .directive('uiScroll', ['$location', '$anchorScroll', function($location, $anchorScroll) {
    return {
      restrict: 'AC',
      link: function(scope, el, attr) {
        el.on('click', function(e) {
          $location.hash(attr.uiScroll);
          $anchorScroll();
        });
      }
    };
  }])
  .directive('uiFullscreen', ['uiLoad', function(uiLoad) {
    return {
      restrict: 'AC',
      template:'<i class="fa fa-expand fa-fw text"></i><i class="fa fa-compress fa-fw text-active"></i>',
      link: function(scope, el, attr) {
        el.addClass('hide');
        uiLoad.load('js/libs/screenfull.min.js').then(function(){
          if (screenfull.enabled) {
            el.removeClass('hide');
          }
          el.on('click', function(){
            var target;
            attr.target && ( target = $(attr.target)[0] );            
            el.toggleClass('active');
            screenfull.toggle(target);
          });
        });
      }
    };
  }])
  .directive('uiButterbar', ['$rootScope', '$anchorScroll', function($rootScope, $anchorScroll) {
     return {
      restrict: 'AC',
      template:'<span class="bar"></span>',
      link: function(scope, el, attrs) {        
        el.addClass('butterbar hide');        
        scope.$on('$stateChangeStart', function(event) {
          $anchorScroll();
          el.removeClass('hide').addClass('active');
        });
        scope.$on('$stateChangeSuccess', function( event, toState, toParams, fromState ) {
          event.targetScope.$watch('$viewContentLoaded', function(){
            el.addClass('hide').removeClass('active');
          })
        });
      }
     };
  }])
  .directive('setNgAnimate', ['$animate', function ($animate) {
    return {
        link: function ($scope, $element, $attrs) {
            $scope.$watch( function() {
                return $scope.$eval($attrs.setNgAnimate, $scope);
            }, function(valnew, valold){
                $animate.enabled(!!valnew, $element);
            });
        }
    };
  }])
  ;



/**
 * app.filters
 */
angular.module('app.filters', [])
    .filter('fromNow', function() {
        return function(date) {
            return moment(date).fromNow();
        }
    })
    ;


/**
 * app.services
 */
angular.module('app.services', ['ngCookies', 'base64'])
  .factory('oauthService', ['$http', '$q', '$cookies', '$base64', 'APP_CONFIG', '$rootScope',
    function ($http, $q, $cookies, $base64, APP_CONFIG, $rootScope) {
        $rootScope.app = $rootScope.app || {};
        $rootScope.app.oauth = {
            access_token: '',
            token_type: '',
            expiresAt: 0 //s
        };

        var service = {};

        /*
        * current time, unit: ms
        */
        function getTime() {
            return new Date().getTime();
        }

        /*
        * form url and endcode
        */
        function formUrlEncode(obj) {
            var str = [];
            for (var p in obj)
                str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
            return str.join('&');
        }


        /*
       * generate Basic Authentication header
       */
        function getBasicAuthentication() {
            var headerValue = 'Basic ' + $base64.encode(APP_CONFIG.appId + ':' + APP_CONFIG.appKey);
            return {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Authorization': headerValue
            };
        }

        /*
        * return token if it's valid, otherwise return undefined
        */
        service.getToken = function () {
            // load from cookies
            if ($rootScope.app.oauth.expiresAt == 0) {
                var cookieAuth = $cookies.getObject(APP_CONFIG.tokenCookieKey);
                if (angular.isDefined(cookieAuth)) {
                    $rootScope.app.oauth = cookieAuth;
                }
            }

            if ($rootScope.app.oauth.expiresAt > getTime()) {
                return $rootScope.app.oauth;
            }
            return undefined;
        };

        function saveToken(tokenResult) {
            $rootScope.app.oauth.access_token = tokenResult.access_token;
            $rootScope.app.oauth.token_type = tokenResult.token_type === 'basic' ? 'Basic' : tokenResult.token_type === 'bearer' ? 'Bearer' : tokenResult.token_type;
            $rootScope.app.oauth.expiresAt = getTime() + tokenResult.expires_in * 1e3;
            $cookies.putObject(APP_CONFIG.tokenCookieKey, $rootScope.app.oauth);
        }

        /*
        * basic token of client. must resovle.
        */
        service.getBasicTokenAsync = function () {
            var defer = $q.defer();
            var clientTokenConfig = {
                method: 'POST',
                url: '/Token',
                headers: getBasicAuthentication(),
                transformRequest: formUrlEncode,
                data: { grant_type: 'client_credentials' }
            };
            $http(clientTokenConfig)
              .success(function (result) {
                  saveToken(result);
                  defer.resolve({ success: true });
              })
              .error(function (err) {
                  console.error('get client token failed.');
                  console.error(err);
                  defer.resolve({ success: false, error: err });
              });

            return defer.promise;
        };


        /*
        * get user's token when got authorization token from sso 
        * must resolve
        */
        service.getUserTokenAsync = function (userName, password, openId) {
            var defer = $q.defer();
            if (userName === '' && password === '') {
                //try to get token from cookies first when password is empty
                if (angular.isDefined(service.getToken())) {
                    defer.resolve({ success: true });
                    return defer.promise;
                }
            }
            var headers = getBasicAuthentication();
            headers[APP_CONFIG.openIdHeaderName] = openId || '';
            var clientTokenConfig = {
                method: 'POST',
                url: '/Token',
                headers: headers,
                transformRequest: formUrlEncode,
                data: {
                    'grant_type': 'password',
                    'username': userName,
                    'password': password
                }
            };
            $http(clientTokenConfig)
              .success(function (result) {
                  saveToken(result);
                  defer.resolve({ success: true });
              })
              .error(function (err) {
                  defer.resolve({ success: false, error: err.error_description || '用户名或者密码错误' });
                  console.error(err);
              });
            return defer.promise;
        };

        /*
        * clear the authorization
        */
        service.clear = function () {
            $rootScope.app.oauth = {
                access_token: '',
                token_type: '',
                expiresAt: 0 //s
            };
            $rootScope.app.user={Id:''};
            $cookies.remove(APP_CONFIG.tokenCookieKey);
        }
        /*
        * loadToken when app started
        */
        service.loadTokenAsync = function () {
            if (angular.isDefined(service.getToken())) {
                var defer = $q.defer();
                defer.resolve({ success: true });
                return defer.promise;
            }
            return service.getBasicTokenAsync();
        };
        /*
        * logout
        */
        service.logoutAsync = function () {
            var defer = $q.defer();
            if (!angular.isDefined(service.getToken())
              || !angular.isDefined($rootScope.app.user)
              || $rootScope.app.user.Id==='') {
                defer.resolve();
            } else {
                var clientTokenConfig = {
                    method: 'POST',
                    url: '/api/Account/Logout'
                };
                $http(clientTokenConfig)
                  .success(function () {
                      service.clear();
                      defer.resolve(true);
                  }).error(function (x) {
                      defer.resolve(false);
                      console.error(x);
                  });
            }
            return defer.promise;
        };

        return service;
    }
  ])
  .factory('appInterceptor', [
    '$rootScope', '$q', 'APP_CONFIG',
    function ($rootScope, $q, APP_CONFIG) {
        var isLogin = true;
        $rootScope.app = $rootScope.app || {};

        function startWith(str, start) {
            if (!str) return false;
            return str.substring(0, start.length) === start;
        }

        function isAbsolute(url) {
            return startWith(url, 'http://') || startWith(url, 'https://');
        }

        function getTime(time) {
            return (time || new Date()).getTime();
        }

        /**
         * 将Api请求指向Api服务器Host
         * @param {} config 
         * @returns {} 
         */
        function isApiRequest(config) {
            var isApi = false;
            if (!isAbsolute(config.url)) {
                //相对地址
                isApi = config.method === 'POST' || startWith(config.url, APP_CONFIG.apiPrefix);
            }
            if (isApi) {
                config.url = APP_CONFIG.apiHost + config.url;
            }
            return isApi;
        }

        function getToken() {
            // load from cookies
            if (!$rootScope.app.oauth || $rootScope.app.oauth.expiresAt == 0) {
                return '';
            }
            if ($rootScope.app.oauth && $rootScope.app.oauth.expiresAt > getTime()) {
                return $rootScope.app.oauth.token_type + ' ' + $rootScope.app.oauth.access_token;
            }
            return '';
        }

        function sayNotLogin() {
            if (isLogin) {
                isLogin = false;
                $rootScope.$emit(APP_CONFIG.eventUserNotLogin, 'notLogin');
            }
        }

        return {
            request: function (config) {
                if (!config.url) return $q.reject(config);
                //add authorization header except token request
                if (isApiRequest(config)) {
                    if (angular.isDefined(config.headers.Authorization) === false) {
                        var token = getToken();
                        if (token === '') {
                            sayNotLogin();
                            return $q.reject(config);
                        }
                        config.headers.Authorization = token;
                    }
                }
                if (config.loading !== false) $rootScope.setLoading(1);
                return config;
            },
            response: function (response) {
                if (response.config && response.config.loading !== false) $rootScope.setLoading(-1);
                !isLogin && (isLogin = true);
                return response;
            },
            responseError: function (response) {
                if (response.config && response.config.loading !== false) $rootScope.setLoading(-1);
                $rootScope.$emit(APP_CONFIG.eventHttpError, response.status);
                return $q.reject(response);
            }
        };
    }
  ])
  /**
   * 封装 alert、confirm、toast
   */
  .factory('notification', [
    '$rootScope', '$modal',
    function ($rootScope, $modal) {
        var service = {};
        service.alert = function (msg, type, timeout) {
            if ($rootScope.modalInstance) {
                $rootScope.modalInstance.dismiss();
            }
            type = type || 'error';
            timeout = timeout || 10;
            msg = msg || '操作失败，请稍后再试';
            $rootScope.modalInstance = $modal.open({
                template: '<div class="modal-header"><p class="modal-title">提示</p></div>'
                + '<div class="modal-body"><p><i class="fa ' + (type === 'success' ? 'fa-check-circle text-success' : type === 'error' ? 'fa-times-circle text-danger' : 'fa-info-circle') + '"></i> ' + msg + '</p></div>'
                + '<div class="modal-footer"><p><small>{{tick}}秒后自动关闭</small><button class="btn btn-primary btn-ok" ng-click="closeAlert($event)">确定</button><p><div>',
                windowClass: 'alert-modal',
                backdrop: true,
                controller: ['$scope', '$interval', function ($scope, $interval) {
                    $scope.tick = timeout;
                    var timer = $interval(function () {
                        $scope.tick > 0 && ($scope.tick--);
                        if ($scope.tick <= 0) {
                            $interval.cancel(timer);
                            timer = undefined;
                            $rootScope.modalInstance.dismiss('timeout');
                        }
                    }, 1e3);
                    //close alert
                    $scope.closeAlert = function ($event) {
                        $rootScope.modalInstance.dismiss($event);
                    };
                    $scope.$on('$destroy', function () {
                        if (timer) {
                            $interval.cancel(timer);
                            timer = undefined;
                        }
                    });
                }]
            });
        };

        service.error = function (msg) {
            service.alert(msg, 'error');
        };

        service.success = function (msg) {
            service.alert(msg, 'success');
        };
        return service;
    }
  ])
  /**
   * 账户服务
   */
  .factory('accountService', [
    '$http', '$q', '$rootScope', 'APP_CONFIG',
    function ($http, $q, $rootScope, APP_CONFIG) {
        $rootScope.app = $rootScope.app || {};
        $rootScope.app.user = $rootScope.app.user || {};

        var service = {};
        /*
         * request user's profile
         */
        service.getUserDataAsync = function (force) {
            var defer = $q.defer();
            var savedUser = service.getLocalUserData();
            if (!force && angular.isDefined(savedUser)) {
                defer.resolve({ success: true, data: savedUser });
            }
            else {
                $http.get('/api/account/userInfo')
                  .success(function (result) {
                      if (result.Code >= 0) {
                          $rootScope.app.user = result.Data;
                          defer.resolve({ success: true, data: $rootScope.app.user });
                      } else {
                          defer.resolve({ success: false, error: result.Message });
                      }
                  })
                  .error(function (x) {
                      defer.resolve({ success: false, error: '查询用户信息失败' });
                      console.log(x);
                  });
            }
            return defer.promise;
        }
        /*
         * local user data saved in cookie when logined
         */
        service.getLocalUserData = function () {
            if (angular.isDefined($rootScope.app.user.Id) && $rootScope.app.user.Id !== '') {
                return $rootScope.app.user;
            }
            return undefined;
        };

        /**
         * 创建用户
         */
        service.createAsync = function (userName,email, password) {
            var defer = $q.defer();
            $http({
                method: 'POST',
                url: '/api/Account/Register',
                data: {
                    UserName: userName,
                    Email:email,
                    Password: password
                }
            }).success(function (result) {
                if (result.Code >= 0) defer.resolve();
                else defer.reject(result.Message);
            }).error(function (x) {
                console.error(x);
                defer.reject('创建用户失败，请稍后再试');
            });

            return defer.promise;
        };

        /**
         * 清除当前用户信息，保留游客数据
         */
        service.clearUser = function () {
            $rootScope.app.user = {Id:''};
        };

        /**
         * 判断用户是否登录
         */
        service.isLogin = function () {
            return $rootScope.app.user.Id !== '';
        };

        return service;
    }
  ])
;

/**
 * app.controllers
 */
angular.module('app.controllers', ['ngCookies'])
  .controller('AppCtrl', ['$scope', '$localStorage', '$window', '$state', '$rootScope', 'APP_CONFIG', '$timeout','$translate',
function ($scope, $localStorage, $window, $state, $rootScope, APP_CONFIG, $timeout,$translate) {
        // add 'ie' classes to html
        var isIE = !!navigator.userAgent.match(/MSIE/i);
        isIE && angular.element($window.document.body).addClass('ie');
        isSmartDevice($window) && angular.element($window.document.body).addClass('smart');

        // config
        $rootScope.app = $rootScope.app || {};

        var defaultAppConfig = {
            name: 'KLUFrame',
            shortName: 'KLUFrame',
            version: '1.0.0',
            // for chart colors
            color: {
                primary: '#7266ba',
                info: '#23b7e5',
                success: '#27c24c',
                warning: '#fad733',
                danger: '#f05050',
                light: '#e8eff0',
                dark: '#3a3f51',
                black: '#1c2b36'
            },
            settings: {
                themeID: 1,
                navbarHeaderColor: 'bg-black',
                navbarCollapseColor: 'bg-white-only',
                asideColor: 'bg-black',
                headerFixed: true,
                asideFixed: false,
                asideFolded: false
            }
        };

        $rootScope.app = angular.extend($rootScope.app || {}, defaultAppConfig);

        // save settings to local storage
        if (angular.isDefined($localStorage.settings)) {
            $scope.app.settings = $localStorage.settings;
        } else {
            $localStorage.settings = $scope.app.settings;
        }
        $scope.$watch('app.settings', function () { $localStorage.settings = $scope.app.settings; }, true);

        // angular translate
        $scope.lang = { isopen: false };
        $scope.langs = { en: 'English', de_DE: 'German', it_IT: 'Italian', zh_CN: '中文' };
        $scope.selectLang = $scope.langs[$translate.proposedLanguage()] || "zh_CN";
        $scope.setLang = function (langKey, $event) {
            // set the current lang
            $scope.selectLang = $scope.langs[langKey];
            // You can change the language during runtime
            $translate.use(langKey);
            $scope.lang.isopen = !$scope.lang.isopen;
        };

        function isSmartDevice($window) {
            // Adapted from http://www.detectmobilebrowsers.com
            var ua = $window['navigator']['userAgent'] || $window['navigator']['vendor'] || $window['opera'];
            // Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices
            return (/iPhone|iPod|iPad|Silk|Android|BlackBerry|Opera Mini|IEMobile/).test(ua);
        }

        //在http请求时显示loading
        $rootScope.delayLoading = 0;
        $rootScope.setLoading=function(count){
            $rootScope.delayLoading+=count;
            if($rootScope.delayLoading>0){
                $timeout(function () {
                    if ($rootScope.delayLoading > 0) {
                        !$rootScope.loading && ($rootScope.loading = true);
                    }
                }, 100);
            }else{
              $rootScope.loading && ($rootScope.loading = false);
            }
        };

        //页面跳转状态
        $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {

        });
        $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
            if ($rootScope.modalInstance) {
                $rootScope.modalInstance.dismiss();
            }
        });
        //用户未登录
        $rootScope.$on(APP_CONFIG.eventUserNotLogin, function () {
            $state.go('access.signin');
        });

        //http请求异常
        $rootScope.$on(APP_CONFIG.eventHttpError, function (event, error) {
            switch (error) {
                case 401:
                    $state.go('access.signin');
                    break;
                case 403:
                    $state.go('app.forbidden');
                case 400:
                case 404:
                case 408:
                    //timeout
                default:
                    break;
            }
        });

    }])

  // bootstrap controller
  .controller('AccordionDemoCtrl', ['$scope', function($scope) {
    $scope.oneAtATime = true;

    $scope.groups = [
      {
        title: 'Accordion group header - #1',
        content: 'Dynamic group body - #1'
      },
      {
        title: 'Accordion group header - #2',
        content: 'Dynamic group body - #2'
      }
    ];

    $scope.items = ['Item 1', 'Item 2', 'Item 3'];

    $scope.addItem = function() {
      var newItemNo = $scope.items.length + 1;
      $scope.items.push('Item ' + newItemNo);
    };

    $scope.status = {
      isFirstOpen: true,
      isFirstDisabled: false
    };
  }])
  .controller('AlertDemoCtrl', ['$scope', function($scope) {
    $scope.alerts = [
      { type: 'success', msg: 'Well done! You successfully read this important alert message.' },
      { type: 'info', msg: 'Heads up! This alert needs your attention, but it is not super important.' },
      { type: 'warning', msg: 'Warning! Best check yo self, you are not looking too good...' }
    ];

    $scope.addAlert = function() {
      $scope.alerts.push({type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.'});
    };

    $scope.closeAlert = function(index) {
      $scope.alerts.splice(index, 1);
    };
  }])
  .controller('ButtonsDemoCtrl', ['$scope', function($scope) {
    $scope.singleModel = 1;

    $scope.radioModel = 'Middle';

    $scope.checkModel = {
      left: false,
      middle: true,
      right: false
    };
  }])
  .controller('CarouselDemoCtrl', ['$scope', function($scope) {
    $scope.myInterval = 5000;
    var slides = $scope.slides = [];
    $scope.addSlide = function() {
      slides.push({
        image: 'img/c' + slides.length + '.jpg',
        text: ['Carousel text #0','Carousel text #1','Carousel text #2','Carousel text #3'][slides.length % 4]
      });
    };
    for (var i=0; i<4; i++) {
      $scope.addSlide();
    }
  }])
  .controller('DropdownDemoCtrl', ['$scope', function($scope) {
    $scope.items = [
      'The first choice!',
      'And another choice for you.',
      'but wait! A third!'
    ];

    $scope.status = {
      isopen: false
    };

    $scope.toggled = function(open) {
      //console.log('Dropdown is now: ', open);
    };

    $scope.toggleDropdown = function($event) {
      $event.preventDefault();
      $event.stopPropagation();
      $scope.status.isopen = !$scope.status.isopen;
    };
  }])
  .controller('ModalDemoCtrl', ['$scope', '$modal', '$log', function($scope, $modal, $log) {
    $scope.items = ['item1', 'item2', 'item3'];
    var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
      $scope.items = items;
      $scope.selected = {
        item: $scope.items[0]
      };

      $scope.ok = function () {
        $modalInstance.close($scope.selected.item);
      };

      $scope.cancel = function () {
        $modalInstance.dismiss('cancel');
      };
    };

    $scope.open = function (size) {
      var modalInstance = $modal.open({
        templateUrl: 'myModalContent.html',
        controller: ModalInstanceCtrl,
        size: size,
        resolve: {
          items: function () {
            return $scope.items;
          }
        }
      });

      modalInstance.result.then(function (selectedItem) {
        $scope.selected = selectedItem;
      }, function () {
        $log.info('Modal dismissed at: ' + new Date());
      });
    };
  }])
  .controller('PaginationDemoCtrl', ['$scope', '$log', function($scope, $log) {
    $scope.totalItems = 64;
    $scope.currentPage = 4;

    $scope.setPage = function (pageNo) {
      $scope.currentPage = pageNo;
    };

    $scope.pageChanged = function() {
      $log.info('Page changed to: ' + $scope.currentPage);
    };

    $scope.maxSize = 5;
    $scope.bigTotalItems = 175;
    $scope.bigCurrentPage = 1;
  }])
  .controller('PopoverDemoCtrl', ['$scope', function($scope) {
    $scope.dynamicPopover = 'Hello, World!';
    $scope.dynamicPopoverTitle = 'Title';
  }])
  .controller('ProgressDemoCtrl', ['$scope', function($scope) {
    $scope.max = 200;

    $scope.random = function() {
      var value = Math.floor((Math.random() * 100) + 1);
      var type;

      if (value < 25) {
        type = 'success';
      } else if (value < 50) {
        type = 'info';
      } else if (value < 75) {
        type = 'warning';
      } else {
        type = 'danger';
      }

      $scope.showWarning = (type === 'danger' || type === 'warning');

      $scope.dynamic = value;
      $scope.type = type;
    };
    $scope.random();

    $scope.randomStacked = function() {
      $scope.stacked = [];
      var types = ['success', 'info', 'warning', 'danger'];

      for (var i = 0, n = Math.floor((Math.random() * 4) + 1); i < n; i++) {
          var index = Math.floor((Math.random() * 4));
          $scope.stacked.push({
            value: Math.floor((Math.random() * 30) + 1),
            type: types[index]
          });
      }
    };
    $scope.randomStacked();
  }])
  .controller('TabsDemoCtrl', ['$scope', function($scope) {
    $scope.tabs = [
      { title:'Dynamic Title 1', content:'Dynamic content 1' },
      { title:'Dynamic Title 2', content:'Dynamic content 2', disabled: true }
    ];
  }])
  .controller('RatingDemoCtrl', ['$scope', function($scope) {
    $scope.rate = 7;
    $scope.max = 10;
    $scope.isReadonly = false;

    $scope.hoveringOver = function(value) {
      $scope.overStar = value;
      $scope.percent = 100 * (value / $scope.max);
    };
  }])
  .controller('TooltipDemoCtrl', ['$scope', function($scope) {
    $scope.dynamicTooltip = 'Hello, World!';
    $scope.dynamicTooltipText = 'dynamic';
    $scope.htmlTooltip = 'I\'ve been made <b>bold</b>!';
  }])
  .controller('TypeaheadDemoCtrl', ['$scope', '$http', function($scope, $http) {
    $scope.selected = undefined;
    $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
    // Any function returning a promise object can be used to load values asynchronously
    $scope.getLocation = function(val) {
      return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
        params: {
          address: val,
          sensor: false
        }
      }).then(function(res){
        var addresses = [];
        angular.forEach(res.data.results, function(item){
          addresses.push(item.formatted_address);
        });
        return addresses;
      });
    };
  }])
  .controller('DatepickerDemoCtrl', ['$scope', function($scope) {
    $scope.today = function() {
      $scope.dt = new Date();
    };
    $scope.today();

    $scope.clear = function () {
      $scope.dt = null;
    };

    // Disable weekend selection
    $scope.disabled = function(date, mode) {
      return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
    };

    $scope.toggleMin = function() {
      $scope.minDate = $scope.minDate ? null : new Date();
    };
    $scope.toggleMin();

    $scope.open = function($event) {
      $event.preventDefault();
      $event.stopPropagation();

      $scope.opened = true;
    };

    $scope.dateOptions = {
      formatYear: 'yy',
      startingDay: 1,
      class: 'datepicker'
    };

    $scope.initDate = new Date('2016-15-20');
    $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
    $scope.format = $scope.formats[0];
  }])
  .controller('TimepickerDemoCtrl', ['$scope', function($scope) {
    $scope.mytime = new Date();

    $scope.hstep = 1;
    $scope.mstep = 15;

    $scope.options = {
      hstep: [1, 2, 3],
      mstep: [1, 5, 10, 15, 25, 30]
    };

    $scope.ismeridian = true;
    $scope.toggleMode = function() {
      $scope.ismeridian = ! $scope.ismeridian;
    };

    $scope.update = function() {
      var d = new Date();
      d.setHours( 14 );
      d.setMinutes( 0 );
      $scope.mytime = d;
    };

    $scope.changed = function () {
      //console.log('Time changed to: ' + $scope.mytime);
    };

    $scope.clear = function() {
      $scope.mytime = null;
    };
  }])

  // Form controller
  .controller('FormDemoCtrl', ['$scope', function($scope) {
    $scope.notBlackListed = function(value) {
      var blacklist = ['bad@domain.com','verybad@domain.com'];
      return blacklist.indexOf(value) === -1;
    }

    $scope.val = 15;
    var updateModel = function(val){
      $scope.$apply(function(){
        $scope.val = val;
      });
    };
    angular.element("#slider").on('slideStop', function(data){
      updateModel(data.value);
    });

    $scope.select2Number = [
      {text:'First',  value:'One'},
      {text:'Second', value:'Two'},
      {text:'Third',  value:'Three'}
    ];

    $scope.list_of_string = ['tag1', 'tag2']
    $scope.select2Options = {
        'multiple': true,
        'simple_tags': true,
        'tags': ['tag1', 'tag2', 'tag3', 'tag4']  // Can be empty list.
    };

  }])

  // Flot Chart controller 
  .controller('FlotChartDemoCtrl', ['$scope', function($scope) {
    $scope.d = [ [1,6.5],[2,6.5],[3,7],[4,8],[5,7.5],[6,7],[7,6.8],[8,7],[9,7.2],[10,7],[11,6.8],[12,7] ];

    $scope.d0_1 = [ [0,7],[1,6.5],[2,12.5],[3,7],[4,9],[5,6],[6,11],[7,6.5],[8,8],[9,7] ];

    $scope.d0_2 = [ [0,4],[1,4.5],[2,7],[3,4.5],[4,3],[5,3.5],[6,6],[7,3],[8,4],[9,3] ];

    $scope.d1_1 = [ [10, 120], [20, 70], [30, 70], [40, 60] ];

    $scope.d1_2 = [ [10, 50],  [20, 60], [30, 90],  [40, 35] ];

    $scope.d1_3 = [ [10, 80],  [20, 40], [30, 30],  [40, 20] ];

    $scope.d2 = [];

    for (var i = 0; i < 20; ++i) {
      $scope.d2.push([i, Math.sin(i)]);
    }   

    $scope.d3 = [ 
      { label: "iPhone5S", data: 40 }, 
      { label: "iPad Mini", data: 10 },
      { label: "iPad Mini Retina", data: 20 },
      { label: "iPhone4S", data: 12 },
      { label: "iPad Air", data: 18 }
    ];

    $scope.getRandomData = function() {
      var data = [],
      totalPoints = 150;
      if (data.length > 0)
        data = data.slice(1);
      while (data.length < totalPoints) {
        var prev = data.length > 0 ? data[data.length - 1] : 50,
          y = prev + Math.random() * 10 - 5;
        if (y < 0) {
          y = 0;
        } else if (y > 100) {
          y = 100;
        }
        data.push(y);
      }
      // Zip the generated y values with the x values
      var res = [];
      for (var i = 0; i < data.length; ++i) {
        res.push([i, data[i]])
      }
      return res;
    }

    $scope.d4 = $scope.getRandomData();
  }])

  // jVectorMap controller
  .controller('JVectorMapDemoCtrl', ['$scope', function($scope) {
    $scope.world_markers = [
      {latLng: [41.90, 12.45], name: 'Vatican City'},
      {latLng: [43.73, 7.41], name: 'Monaco'},
      {latLng: [-0.52, 166.93], name: 'Nauru'},
      {latLng: [-8.51, 179.21], name: 'Tuvalu'},
      {latLng: [43.93, 12.46], name: 'San Marino'},
      {latLng: [47.14, 9.52], name: 'Liechtenstein'},
      {latLng: [7.11, 171.06], name: 'Marshall Islands'},
      {latLng: [17.3, -62.73], name: 'Saint Kitts and Nevis'},
      {latLng: [3.2, 73.22], name: 'Maldives'},
      {latLng: [35.88, 14.5], name: 'Malta'},
      {latLng: [12.05, -61.75], name: 'Grenada'},
      {latLng: [13.16, -61.23], name: 'Saint Vincent and the Grenadines'},
      {latLng: [13.16, -59.55], name: 'Barbados'},
      {latLng: [17.11, -61.85], name: 'Antigua and Barbuda'},
      {latLng: [-4.61, 55.45], name: 'Seychelles'},
      {latLng: [7.35, 134.46], name: 'Palau'},
      {latLng: [42.5, 1.51], name: 'Andorra'},
      {latLng: [14.01, -60.98], name: 'Saint Lucia'},
      {latLng: [6.91, 158.18], name: 'Federated States of Micronesia'},
      {latLng: [1.3, 103.8], name: 'Singapore'},
      {latLng: [1.46, 173.03], name: 'Kiribati'},
      {latLng: [-21.13, -175.2], name: 'Tonga'},
      {latLng: [15.3, -61.38], name: 'Dominica'},
      {latLng: [-20.2, 57.5], name: 'Mauritius'},
      {latLng: [26.02, 50.55], name: 'Bahrain'},
      {latLng: [0.33, 6.73], name: 'São Tomé and Príncipe'}
    ];

    $scope.usa_markers = [
      {latLng: [40.71, -74.00], name: 'New York'},
      {latLng: [34.05, -118.24], name: 'Los Angeles'},
      {latLng: [41.87, -87.62], name: 'Chicago'},
      {latLng: [29.76, -95.36], name: 'Houston'},
      {latLng: [39.95, -75.16], name: 'Philadelphia'},
      {latLng: [38.90, -77.03], name: 'Washington'},
      {latLng: [37.36, -122.03], name: 'Silicon Valley'}
    ];
  }])
;
    
